
package com.huaweicloud.saaslanding.install.util;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.huaweicloud.saaslanding.basic.enumeration.MonoDeploymentInfoBelongEnum;
import com.huaweicloud.saaslanding.basic.utils.EncryptionUtil;
import com.huaweicloud.saaslanding.dao.common.entity.app.MonoAppDeployment;
import com.huaweicloud.saaslanding.dao.common.entity.app.MonoAppLicenseModule;
import com.huaweicloud.saaslanding.dao.common.entity.app.MonoAppPackageEcsSpec;
import com.huaweicloud.saaslanding.dao.common.entity.cloudservice.IamAccountInfo;
import com.huaweicloud.saaslanding.dao.common.entity.deployedresource.EcsResource;
import com.huaweicloud.saaslanding.dao.common.entity.security.SecurityGroup;
import com.huaweicloud.saaslanding.dao.common.repository.app.MonoAppDeploymentBaseMapper;
import com.huaweicloud.saaslanding.dao.common.repository.app.MonoAppLicenseModuleBaseMapper;
import com.huaweicloud.saaslanding.dao.common.repository.app.MonoAppPackageEcsSpecBaseMapper;
import com.huaweicloud.saaslanding.dao.common.repository.cloudservice.IamAccountInfoBaseMapper;
import com.huaweicloud.saaslanding.dao.common.repository.deployedresource.EcsResourceBaseMapper;
import com.huaweicloud.saaslanding.dao.common.repository.security.SecurityGroupBaseMapper;
import com.huaweicloud.saaslanding.huawei.ecs.EcsApi;
import com.huaweicloud.saaslanding.huawei.ecs.model.RootVolume;
import com.huaweicloud.saaslanding.huawei.ecs.model.Server;
import com.huaweicloud.saaslanding.huawei.ecs.model.Subnet;
import com.huaweicloud.saaslanding.huawei.ecs.request.EcsCreateRequest;
import com.huaweicloud.saaslanding.huawei.ecs.response.EcsCreateResponse;
import com.huaweicloud.saaslanding.install.dto.CreateEcsDto;
import com.huaweicloud.saaslanding.install.properties.Vpc;

import jakarta.annotation.Resource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * 功能描述
 *
 * @since 2022-12-20
 */
@Component
public class EcsApiUtil {

    @Resource
    private MonoAppPackageEcsSpecBaseMapper monoAppPackageEcsSpecBaseMapper;

    @Resource
    private MonoAppDeploymentBaseMapper monoAppDeploymentBaseMapper;

    @Resource
    private ApiHandleUtil apiHandleUtil;

    @Resource
    private EcsResourceBaseMapper ecsResourceBaseMapper;

    @Resource
    private IamAccountInfoBaseMapper iamAccountInfoMapper;

    @Resource
    private Vpc vpc;

    @Resource
    private MonoAppLicenseModuleBaseMapper monoAppLicenseModuleBaseMapper;

    @Resource
    private SecurityGroupBaseMapper securityGroupBaseMapper;

    @Value("${saaslanding.mysql.database}")
    private String database;

    /**
     * 创建ecs资源
     *
     * @param appId 应用id
     * @param moduleId 模块id
     * @param tenantCode 租户code
     * @return ecs资源信息
     */
    public EcsResource createEcs(Long appId, String moduleId, String tenantCode,
        List<com.huaweicloud.saaslanding.huawei.ecs.model.SecurityGroup> securityGroupList) {
        // 单体应用部署信息
        CreateEcsDto createEcsDto = getCreateEcsDto(moduleId, appId, securityGroupList);
        EcsCreateRequest ecsCreateRequest = createEcsRequest(createEcsDto);
        // 创建ECS云服务器
        EcsCreateResponse ecsCreateResponse = EcsApi.create(apiHandleUtil.getIamHeaderMap(appId),
            apiHandleUtil.getProjectId(appId), apiHandleUtil.getEcsEndpoint(appId), ecsCreateRequest);

        // TODO 等ECS创建成功后把私有IP更新到数据库表中

        List<String> serverIds = ecsCreateResponse.getServerIds();
        String serverId = serverIds.get(0);

        // 添加 ECS资源表 hsl_ecs_resource 记录
        EcsResource ecsResource = initEcsResource(appId);
        ecsResource.setName(moduleId).setCloudServerUuid(serverId).setAppId(appId).setTenantCode(tenantCode);
        String adminPwd = createEcsDto.getAdminPass();
        String tenantSalt = apiHandleUtil.getSalt(tenantCode);
        ecsResource.setAdminPass(EncryptionUtil.encrypt(tenantSalt, adminPwd));
        ecsResourceBaseMapper.insert(ecsResource);

        // 把ecs信息更新到App_license表
        List<MonoAppLicenseModule> monoAppLicenseModuleList =
            monoAppLicenseModuleBaseMapper.selectList(new QueryWrapper<MonoAppLicenseModule>().eq("app_id", appId));

        for (int i = 0; i < monoAppLicenseModuleList.size(); i++) {
            MonoAppLicenseModule appLicenseModule = monoAppLicenseModuleList.get(i);
            appLicenseModule.setCloudServerUuid(ecsResource.getCloudServerUuid());

            SecurityGroup securityGroup = securityGroupBaseMapper.selectOne(
                new QueryWrapper<SecurityGroup>().eq("security_group_uuid", securityGroupList.get(i).getId()));
            appLicenseModule.setSecurityGroupId(securityGroup.getId());

            monoAppLicenseModuleBaseMapper.updateById(appLicenseModule);
        }

        return ecsResource;
    }

    /**
     * 获取创建 ECS 所需的请求体数据
     *
     * @param moduleId 租户 appCode
     * @param appId 云商店产品规格标识
     * @return CreateEcsDto
     */
    private CreateEcsDto getCreateEcsDto(String moduleId, Long appId,
        List<com.huaweicloud.saaslanding.huawei.ecs.model.SecurityGroup> securityGroupList) {
        CreateEcsDto createEcsDto = new CreateEcsDto();
        createEcsDto.setEcsName(moduleId);

        MonoAppPackageEcsSpec monoAppPackageEcsSpec =
            monoAppPackageEcsSpecBaseMapper.selectOne(new QueryWrapper<MonoAppPackageEcsSpec>().eq("app_id", appId));

        createEcsDto.setDataVolumeSize(monoAppPackageEcsSpec.getDataVolumeSize())
            .setDataVolumeType(monoAppPackageEcsSpec.getDataVolumeType())
            .setRootVolumeSize(monoAppPackageEcsSpec.getRootVolumeSize())
            .setBandwidthSize(monoAppPackageEcsSpec.getBandwidthSize())
            .setFlavorRef(monoAppPackageEcsSpec.getFlavorRef())
            .setSharetype(monoAppPackageEcsSpec.getSharetype())
            .setImageRef(monoAppPackageEcsSpec.getImageRef())
            .setIpType(monoAppPackageEcsSpec.getIptype());

        // 设置VPC信息和子网信息
        createEcsDto.setVpcId(vpc.getServerVpcId()).setSubnetId(vpc.getLicenseSubnetId());

        // 安全组信息（这里使用默认安全组就行）
        createEcsDto.setSecurityGroupList(securityGroupList);

        MonoAppDeployment monoAppDeployment =
            monoAppDeploymentBaseMapper.selectOne(new QueryWrapper<MonoAppDeployment>().lambda()
                .eq(MonoAppDeployment::getBelongTo, MonoDeploymentInfoBelongEnum.SERVER.getBelongTo())
                .eq(MonoAppDeployment::getIsDel, false)
                .eq(MonoAppDeployment::getAppId, appId));

        // 管理员密码
        IamAccountInfo iamAccountInfo = iamAccountInfoMapper.selectById(monoAppDeployment.getIamId());
        String saasSalt = apiHandleUtil.getSalt(database);
        createEcsDto.setAdminPass(EncryptionUtil.decrypt(saasSalt, iamAccountInfo.getPassword()));

        // TODO 设置启动脚本 createEcsDto.setUserData(initScript());

        return createEcsDto;
    }

    /**
     * 初始化脚本读取
     *
     * @return 脚本
     */
    private String initScript() {
        return "";
    }

    /**
     * 构造 创建ECS（ECS API） 请求体
     *
     * @param createEcsDto 创建 ECS 所需的请求体数据
     * @return ECS API（创建ECS）的请求体
     */
    public EcsCreateRequest createEcsRequest(CreateEcsDto createEcsDto) {

        Server server = new Server();
        // 云服务器名称
        server.setName(createEcsDto.getEcsName());
        // 镜像ID
        server.setImageRef(createEcsDto.getImageRef());
        // 云服务器对应系统盘相关配置
        server.setRootVolume(initVolume(createEcsDto.getRootVolumeType(), createEcsDto.getRootVolumeSize()));
        // 云服务器对应数据盘相关配置
        if (createEcsDto.getDataVolumeType() != null && createEcsDto.getDataVolumeType().trim().length() != 0
            && createEcsDto.getDataVolumeSize() != 0) {
            List<RootVolume> dataVolumes = new ArrayList<>();
            dataVolumes.add(initVolume(createEcsDto.getDataVolumeType(), createEcsDto.getDataVolumeSize()));
            server.setDataVolumes(dataVolumes);
        }
        // 系统规格ID
        server.setFlavorRef(createEcsDto.getFlavorRef());
        // VPC UUID
        server.setVpcid(createEcsDto.getVpcId());
        // 云服务器对应安全组信息
        server.setSecurityGroups(createEcsDto.getSecurityGroupList());
        // 网卡信息
        Subnet subnet = new Subnet();
        subnet.setSubnetId(createEcsDto.getSubnetId());
        List<Subnet> nics = new ArrayList<>();
        nics.add(subnet);
        server.setNics(nics);
        // 管理员帐户初始登录密码
        server.setAdminPass(createEcsDto.getAdminPass());
        // 创建云服务器过程中待注入用户数据
        server.setUserData(createEcsDto.getUserData());
        // 创建云服务器数量
        server.setCount(1);

        // 请求体
        EcsCreateRequest ecsCreateRequest = new EcsCreateRequest();
        // 是否只预检此次请求 json.put("dry_run", true);
        // 弹性云服务器信息
        ecsCreateRequest.setServer(server);

        return ecsCreateRequest;
    }

    /**
     * 初始化磁盘设置
     *
     * @param type 磁盘类型
     * @param size 磁盘大小
     * @return 磁盘设置数据
     */
    public RootVolume initVolume(String type, int size) {
        RootVolume rootVolume = new RootVolume();
        rootVolume.setVolumetype(type);
        rootVolume.setSize(size);
        return rootVolume;
    }

    /**
     * 初始化 hsl_ecs_resource 数据
     *
     * @param appId 应用模板表 id
     * @return EcsResource
     */
    public EcsResource initEcsResource(Long appId) {
        EcsResource ecsResource = new EcsResource();

        MonoAppDeployment monoAppDeployment =
            monoAppDeploymentBaseMapper.selectOne(new QueryWrapper<MonoAppDeployment>().lambda()
                .eq(MonoAppDeployment::getBelongTo, MonoDeploymentInfoBelongEnum.SERVER.getBelongTo())
                .eq(MonoAppDeployment::getIsDel, false)
                .eq(MonoAppDeployment::getAppId, appId));

        ecsResource.setRegion(monoAppDeployment.getRegion());

        return ecsResource;
    }
}
